package service

import (
	"fmt"
	Mysql "gin/database"
	"gin/response"
	"gin/validate"
	"github.com/360EntSecGroup-Skylar/excelize/v2"
	"mime/multipart"
	"strings"
	"time"
)

func getExcelHeader(parsedData [][]string, hasHeader bool) (res []string) {
	if !hasHeader || len(parsedData) == 0 {
		return
	}
	for _, fields := range parsedData {
		for _, field := range fields {
			res = append(res, field)
		}
		break
	}

	return
}

func getExcelBody(parsedData [][]string, header []string) []map[string]string {
	var res []map[string]string
	if len(header) > 0 {

		for _, row := range parsedData {
			rowRes := make(map[string]string)
			if len(row) < len(header) {
				continue
			}

			for fIndex, fieldName := range header {
				rowRes[fieldName] = row[fIndex]
			}
			res = append(res, rowRes)
		}
	} else {
		for _, row := range parsedData {

			rowRes := make(map[string]string)

			for colIndex, colVal := range row {

				rowRes[string(colIndex)] = colVal

			}
			res = append(res, rowRes)
		}
	}
	return res
}

// 格式化粘贴内容
func ExcelFormatPasteData(parsedData [][]string, hasHeader bool, moduleCode string) (res response.ExcelFormatPasteDataResp) {

	res.Fields = GetTableFields(moduleCode)
	res.Header = getExcelHeader(parsedData, hasHeader)

	if hasHeader {
		parsedData = parsedData[1:]
	}
	res.Body = getExcelBody(parsedData[1:], res.Header)
	return
}

// 格式化excel文件
func ExcelFormatFileData(fileImport *multipart.FileHeader, efv validate.ExcelFormatFileData) (res response.ExcelFormatFileDataResp, err error) {

	f, fe := fileImport.Open()
	if fe != nil {
		return res, fe
	}

	defer f.Close()
	ef, efe := excelize.OpenReader(f)
	if efe != nil {
		return res, efe
	}
	sheets := ef.GetSheetList()

	firstSheet := sheets[0]

	ef.SetActiveSheet(ef.GetSheetIndex(firstSheet))

	rows, errRows := ef.GetRows(firstSheet)
	if errRows != nil {
		return res, errRows
	}

	var data [][]string

	for _, row := range rows {
		data = append(data, row)
	}

	res.Header = getExcelHeader(data, efv.HasHeader == "yes")

	if efv.HasHeader == "yes" && len(data) > 2 {
		data = data[1:]
	}
	res.Body = getExcelBody(data, res.Header)
	res.Fields = GetTableFields(efv.ModuleCode)
	return
}

// 数据导入
func ExcelImportData(ev validate.ExcelImportData) int64 {
	fields := GetTableFields(ev.ModuleCode)
	if len(fields) <= 0 {
		return 0
	}

	count, sqlList := buildInsertSql(ev.ModuleCode, ev.HeaderMapping, ev.Body)
	if len(sqlList) > 0 {
		for _, sql := range sqlList {
			Mysql.DB.Exec(sql)
		}
	}
	return count
}

// 生成插入sql
func buildInsertSql(tableName string, headerMap []map[string]string, data []map[string]interface{}) (count int64, sqlList []string) {

	totalFields := GetTableFields(tableName)

	var sqlPrefix = "INSERT INTO `" + tableName + "` ( "

	var fields []string

	fieldsColMap := make(map[string]string)

	var fieldCheckTag = false

	createdCheck := false

	for _, col := range headerMap {

		fieldCheckTag = false
		for _, field := range totalFields {

			if col["field"] == field {
				fieldCheckTag = true
			}
			if field == "created" {
				createdCheck = true
			}

		}

		if fieldCheckTag != true {
			continue
		}

		sqlPrefix += "`" + col["field"] + "`,"
		fields = append(fields, col["field"])
		fieldsColMap[col["field"]] = col["column_name"]
	}

	if len(fieldsColMap) <= 0 {
		return
	}
	if createdCheck {
		sqlPrefix += "`created`,"
	}

	sqlPrefix = strings.TrimRight(sqlPrefix, ",")

	sqlPrefix += " ) VALUES"

	var maxInsertRows = 500

	var realSql = sqlPrefix

	if len(data) <= 0 {
		return
	}

	for index, row := range data {

		if index%maxInsertRows == 0 && index != 0 {

			realSql = strings.TrimRight(realSql, ",")

			sqlList = append(sqlList, realSql)

			realSql = sqlPrefix

		}
		realSql += "("

		for _, col := range fields {

			realSql += "\"" + row[fieldsColMap[col]].(string) + "\","

		}

		if createdCheck {
			realSql += fmt.Sprintf("%d ,", time.Now().Unix())
		}

		realSql = strings.TrimRight(realSql, ",")

		realSql += "),"
		count += 1
	}

	realSql = strings.TrimRight(realSql, ",")

	sqlList = append(sqlList, realSql)

	return
}
